package fr.sedoo.metadata.client.ui.widget.field.impl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.google.gwt.user.client.ui.HorizontalPanel;

import fr.sedoo.commons.client.util.ElementUtil;
import fr.sedoo.commons.client.util.StringUtil;
import fr.sedoo.commons.shared.domain.HasIdentifier;
import fr.sedoo.metadata.client.ui.widget.field.api.IsDisplay;
import fr.sedoo.metadata.client.ui.widget.field.api.IsEditor;
import fr.sedoo.metadata.client.ui.widget.field.constant.FieldConstant;
import fr.sedoo.metadata.client.ui.widget.table.contact.MetadataContactTable;
import fr.sedoo.metadata.shared.domain.MetadataDTO;
import fr.sedoo.metadata.shared.domain.dto.MetadataContactDTO;

public class OtherRoles extends HorizontalPanel implements IsDisplay, IsEditor {
	protected MetadataContactTable table;
	private List<String> roles;

	public OtherRoles(List<String> roles) {
		super();
		this.roles = roles;
		setWidth(FieldConstant.HUNDRED_PERCENT);
		table = new MetadataContactTable(roles);
		table.setAskDeletionConfirmation(false);
		ElementUtil.hide(table);
		table.setVisible(false);
		add(table);
	}

	@Override
	public void display(MetadataDTO metadata) {
		table.enableDisplayMode();
		ElementUtil.show(table);
		table.hideToolBar();
		table.init(filterContact(metadata));
	}

	@Override
	public void reset() {
		table.reset();
	}

	@Override
	public void edit(MetadataDTO metadata) {
		table.showToolBar();
		table.enableEditMode();
		ElementUtil.show(table);
		table.init(filterContact(metadata));
	}

	/**
	 * We filter only the contacts corresponding to the roles manages by the
	 * component. Contacts with similar email are merged
	 * 
	 * @param metadata
	 * @return
	 */
	private List<? extends HasIdentifier> filterContact(MetadataDTO metadata) {
		List<MetadataContactDTO> result = new ArrayList<MetadataContactDTO>();
		Iterator<MetadataContactDTO> iterator = metadata.getContactPart().getResourceContacts().iterator();
		while (iterator.hasNext()) {
			MetadataContactDTO current = MetadataContactDTO.clone(iterator.next());
			String role = current.getRoles();
			if (isManagedRole(role)) {
				if (StringUtil.isEmpty(current.getEmail())) {
					result.add(current);
				} else {
					MetadataContactDTO existing = getContactByEmail(result, StringUtil.trimToEmpty(current.getEmail()));
					if (existing == null) {
						result.add(current);
					} else {
						existing.addRole(role);
					}
				}
			}
		}
		return result;
	}

	private MetadataContactDTO getContactByEmail(List<MetadataContactDTO> contacts, String email) {
		Iterator<MetadataContactDTO> iterator = contacts.iterator();
		while (iterator.hasNext()) {
			MetadataContactDTO current = iterator.next();
			if (StringUtil.trimToEmpty(current.getEmail()).equalsIgnoreCase(email)) {
				return current;
			}
		}
		return null;
	}

	/*
	 * Role provided as parameter come from the Metadata and are singleValueRole
	 */
	private boolean isManagedRole(String value) {
		Iterator<String> iterator = this.roles.iterator();
		while (iterator.hasNext()) {
			if (value.compareToIgnoreCase(iterator.next()) == 0) {
				return true;
			}
		}
		return false;
	}

	@Override
	public void flush(MetadataDTO metadata) {
		ArrayList<MetadataContactDTO> result = new ArrayList<MetadataContactDTO>();
		Iterator<? extends HasIdentifier> iterator = table.getModel().iterator();
		while (iterator.hasNext()) {
			MetadataContactDTO current = (MetadataContactDTO) iterator.next();
			if (StringUtil.isNotEmpty(current.getRoles())) {
				String roles = current.getRoles();
				if (roles.contains(MetadataContactDTO.ROLE_SEPARATOR) == false) {
					// We dont modify the contact
					result.add(current);
				} else {
					// We split the contact with many roles
					String[] aux = roles.split(MetadataContactDTO.ROLE_SEPARATOR);
					for (int i = 0; i < aux.length; i++) {
						MetadataContactDTO clone = MetadataContactDTO.clone(current);
						clone.setRoles(aux[i]);
						result.add(clone);
					}
				}
			}
		}
		metadata.getContactPart().addResourceContacts(result);
	}
}
